//
//  MTVideoVerificationViewController.swift
//  MT
//
//  Created by M on 2019/12/24.
//  Copyright © 2019 张强. All rights reserved.
//

import UIKit
import MTCategory
import ZFPlayer
import AVFoundation
import YPNavigationBarTransition

/// 网络
import Moya
import Result
import RxSwift
import RxCocoa

class MTVideoVerificationViewController: BaseViewController {
    
    /// MTProvider
    private lazy var provider: MTProvider<UploadApi> = {
        return MTProvider<UploadApi>(plugins: [])
    }()
    private let disposeBag = DisposeBag()
    
    /// User MTProvider
    private lazy var user_provider: MTProvider<UserCenterApi> = {
        return MTProvider<UserCenterApi>(plugins: [])
    }()
    
    @objc
    enum VideoVerificationStatus: Int {
        case demo
        case record
        case playback
    }
    var status: VideoVerificationStatus = .record
    
    //上传完成回调
    var completionHandler: ((_ url: String, _ thumb: UIImage)->())?
    private var thumb: UIImage?

    /// 播放示例视频 imageView
    lazy var demoVideoImageView: UIImageView = {
        let imgView = UIImageView()
        imgView.contentMode = .scaleAspectFill
        return imgView
    }()
    
    /// 顶部透明遮罩
    lazy var topCoverView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        return view
    }()
    
    /// 底部透明遮罩
    lazy var botCoverView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        return view
    }()
    
    /// 顶部文字说明
    lazy var topLabel: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.textAlignment = .center
        return label
    }()
    
    /// 按钮
    lazy var mainButton: UIButton = {
        let btn = UIButton()
        btn.backgroundColor = UIColor.theme.main
        btn.setTitle("长按录制", for: .normal)
        btn.setTitleColor(UIColor(hex: 0x161616), for: .normal)
        btn.titleLabel?.font = PingFangSCSemiboldFont(16)
        btn.adjustsImageWhenHighlighted = false
        btn.layer.cornerRadius = 22
//        btn.addTarget(self, action: #selector(videoVerificationController(didClickMainButton:)), for: .touchUpInside)
        btn.addTarget(self, action: #selector(videoVerificationController(mainButtonTouchUp:)), for: .touchUpInside)
        btn.addTarget(self, action: #selector(videoVerificationController(mainButtonTouchDown:)), for: .touchDown)
        return btn
    }()
    
    /// 提示文字
    lazy var tipsLabel: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.font = PingFangSCRegularFont(14)
        label.textColor = .white
        label.textAlignment = .center
        label.isUserInteractionEnabled = true
        let t = UITapGestureRecognizer(target: self, action: #selector(videoVerificationController(didTapTipsLabel:)))
        label.addGestureRecognizer(t)
        return label
    }()
    
    // MARK: ------------------ 视频播放 ----------------------
    var playerItem: AVPlayerItem?
    var player: AVPlayer?
    var playerLayer: AVPlayerLayer?

    // MARK: ------------------ 视频录制 ----------------------
    /// 录制时间
    var recordTime: TimeInterval = 0.0
    /// 视频录制
    var writer: AVAssetWriter?
    var videoInput: AVAssetWriterInput?
    var audioInput: AVAssetWriterInput?
    var adaptor: AVAssetWriterInputPixelBufferAdaptor?
    
    /// 拍摄视频本地地址
    var local_video_path: String {
        let s = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as AnyObject
        return s.appending("/verifyVideo.mov")
    }
    /// 是否正在拍摄
    var isRecording: Bool = false
    /// 视频采集队列
    lazy var videoCaptureQueue: DispatchQueue = {
        return DispatchQueue(label: "com.MT.videoCaptureQueue")
    }()
    /// 音频采集队列
    lazy var audioCaptureQueue: DispatchQueue = {
        return DispatchQueue(label: "com.MT.audioCaptureQueue")
    }()
    /// AVCaptureSession
    lazy var captureSession: AVCaptureSession = {
        let session = AVCaptureSession()
        session.sessionPreset = .hd1280x720
        let deviceInput: AVCaptureDeviceInput = frontCameraInput
        if session.canAddInput(deviceInput) {
            session.addInput(deviceInput)
        } else { debugPrint("AVCaptureSession addDeviceInput fail") }
        
        if session.canAddOutput(videoOutput) {
            session.addOutput(videoOutput)
        } else { debugPrint("AVCaptureSession addOutput fail") }
        
        if session.canAddInput(audioMicInput) {
            session.addInput(audioMicInput)
        } else { debugPrint("AVCaptureSession addAudioMicInput fail") }
        
        if session.canAddOutput(audioOutput) {
            session.addOutput(audioOutput)
        } else { debugPrint("AVCaptureSession addAudioOutput fail") }
        
        self.videoConnection.videoOrientation = .portrait
        if self.videoConnection.isVideoMirroringSupported {
            self.videoConnection.isVideoMirrored = true
        }
        session.beginConfiguration()
        do {
            try deviceInput.device.lockForConfiguration()
            deviceInput.device.activeVideoMinFrameDuration = CMTimeMake(value: 1, timescale: 30)
            deviceInput.device.unlockForConfiguration()
        } catch {
            debugPrint(error.localizedDescription)
        }
        session.commitConfiguration()
        return session
    }()
    
    /// 前置摄像头输入
    lazy var frontCameraInput: AVCaptureDeviceInput = {
        let backCameraInput = try! AVCaptureDeviceInput(device: frontCamera())
        self.camera = backCameraInput.device
        return backCameraInput
    }()
    /// 视频输出
    fileprivate lazy var videoOutput: AVCaptureVideoDataOutput = {
        let videoOutput = AVCaptureVideoDataOutput()
        let outputSetting: [String:Any] = [kCVPixelBufferPixelFormatTypeKey as String : NSNumber(integerLiteral: Int(kCVPixelFormatType_32BGRA))]
        videoOutput.alwaysDiscardsLateVideoFrames = true
        videoOutput.videoSettings = outputSetting
        videoOutput.setSampleBufferDelegate(self, queue: videoCaptureQueue)
        return videoOutput
    }()
    /// AVCaptureConnection 视频连接
    fileprivate lazy var videoConnection: AVCaptureConnection = {
        let connection = self.videoOutput.connection(with: .video)!
        connection.automaticallyAdjustsVideoMirroring = false
        return connection
    }()
    /// 摄像头
    lazy var camera: AVCaptureDevice? = {
        if #available(iOS 10.0, *) {
            let devices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .front)
            for device in devices.devices {
                if device.position == .front {
                    return device
                }
            }
        } else {
            let devices = AVCaptureDevice.devices(for: .video)
            for device in devices {
                if device.position == .front {
                    return device
                }
            }
        }
        return nil
    }()
    /// 麦克风输入
    fileprivate lazy var audioMicInput: AVCaptureDeviceInput = {
        let mic = AVCaptureDevice.default(for: .audio)!
        let deviceInput = try! AVCaptureDeviceInput(device: mic)
        return deviceInput
    }()
    /// 麦克风输出
    fileprivate lazy var audioOutput: AVCaptureAudioDataOutput = {
        let audioOutput = AVCaptureAudioDataOutput()
        audioOutput.setSampleBufferDelegate(self, queue: audioCaptureQueue)
        return audioOutput
    }()
    lazy var previewLayer: AVCaptureVideoPreviewLayer = {
        let l = AVCaptureVideoPreviewLayer(session: self.captureSession)
        l.videoGravity = .resizeAspectFill
        l.frame = self.view.bounds
       return l
    }()
    
    var alertView: CenterAlertView?
    
    deinit {
        cleanPlayer()
        cleanRecordingConfig()
    }
    
}

// MARK: ------------------ Overrides ----------------------
extension MTVideoVerificationViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
//        demoPlayback()
        initializeUI()
        setTopLabel()
        setTipsLabel()
        cleanPlayer()
        startSession()
    }
    
    override func yp_navigtionBarConfiguration() -> YPNavigationBarConfigurations {
        .backgroundStyleTransparent
    }
    
    override func yp_navigationBarTintColor() -> UIColor! {
        UIColor(hex: 0xFFFFFF)
    }

    override func yp_navigationBackgroundColor() -> UIColor! {
        .clear
    }

    override func yp_navigationBackgroundImage(withIdentifier identifier: AutoreleasingUnsafeMutablePointer<NSString?>!) -> UIImage! {
        return nil
    }
    
    override func back(_ animated: Bool = true) {
        super.back(animated)
        self.alertView?.dismiss()
        self.alertView = nil
        navigationController?.popViewController(animated: true)
    }
    
}

// MARK: ------------------ 初始化 ----------------------
extension MTVideoVerificationViewController {
    
    private func initializeUI() {
        view.backgroundColor = .white
        view.addSubview(topCoverView)
        view.addSubview(botCoverView)
        view.addSubview(topLabel)
        view.addSubview(mainButton)
        view.addSubview(tipsLabel)
        
        topCoverView.snp.makeConstraints { (make) in
            make.top.left.right.equalTo(view)
            make.height.equalTo(156 + ScreenBottomExtraOffset)
        }
        
        botCoverView.snp.makeConstraints { (make) in
            make.bottom.left.right.equalTo(view)
            make.height.equalTo(156 + ScreenBottomExtraOffset)
        }
        
        topLabel.snp.makeConstraints { (make) in
            make.left.equalTo(view).offset(50)
            make.right.equalTo(view).offset(-50)
            make.bottom.equalTo(topCoverView).offset(-15)
        }
        
        mainButton.snp.makeConstraints { (make) in
            make.centerX.equalTo(view)
            make.top.equalTo(botCoverView).offset(46)
            make.width.equalTo(210)
            make.height.equalTo(44)
        }
        
        tipsLabel.snp.makeConstraints { (make) in
            make.centerX.equalTo(view)
            make.top.equalTo(mainButton.snp.bottom).offset(10)
            make.width.equalTo(150)
            make.height.equalTo(20)
        }
    }
    
}

// MARK: ------------------ 事件方法 ----------------------
@objc
extension MTVideoVerificationViewController {
 
    /// 点击主要按钮
    private func videoVerificationController(didClickMainButton sender: UIButton) {
        
        switch status {
            
        case .demo:
            self.status = .record
            setTopLabel()
            setTipsLabel()
            cleanPlayer()
            startSession()
            break
            
        case .record:
            if !isRecording {
                startRecording()
            } else {
                stopRecording { [weak self] in
                    DispatchQueue.main.async {
                        self?.isRecording = false
                        self?.stopCountDown()
                        self?.status = .playback
                        self?.cleanRecordingConfig()
                        self?.stopSession()
                        self?.setTipsLabel()
                        self?.userVideoPlayback()
                    }
                }
            }
            break
            
        case .playback:
            /// 上传并提交
            upload()
            break
        }
        
    }
    
    private func videoVerificationController(mainButtonTouchDown sender: UIButton) {
        if !isRecording {
            startRecording()
        }
    }
    
    private func videoVerificationController(mainButtonTouchUp sender: UIButton) {
        stopRecording { [weak self] in
            guard let weakself = self else { return }
            DispatchQueue.main.async {
                weakself.isRecording = false
                weakself.stopCountDown()
                weakself.status = .playback
                weakself.cleanRecordingConfig()
                weakself.stopSession()
                weakself.setTipsLabel()
                weakself.userVideoPlayback()

                /// 移除方法
                weakself.mainButton.removeTarget(weakself, action: #selector(weakself.videoVerificationController(mainButtonTouchDown:)), for: .touchDown)
                weakself.mainButton.removeTarget(weakself, action: #selector(weakself.videoVerificationController(mainButtonTouchUp:)), for: .touchUpInside)
                /// 添加方法
                weakself.mainButton.addTarget(weakself, action: #selector(weakself.videoVerificationController(didClickMainButton:)), for: .touchUpInside)
            }
        }
    }

    /// 点击 Tips Label
    private func videoVerificationController(didTapTipsLabel tap: UITapGestureRecognizer) {
        if self.status == .playback {
            /// 重新录制
            self.status = .record
            setTopLabel()
            setTipsLabel()
            cleanPlayer()
            startSession()
            recordTime = 0
            
            /// 移除方法
            mainButton.removeTarget(self, action: #selector(videoVerificationController(didClickMainButton:)), for: .touchUpInside)
            /// 添加方法
            mainButton.addTarget(self, action: #selector(videoVerificationController(mainButtonTouchDown:)), for: .touchDown)
            mainButton.addTarget(self, action: #selector(videoVerificationController(mainButtonTouchUp:)), for: .touchUpInside)
        }
    }
    
}

// MARK: ------------------ 其它 ----------------------
extension MTVideoVerificationViewController {
    
    /// 设置顶部文字
    private func setTopLabel() {
        if status == .demo {
            let mas = NSMutableAttributedString()
            let as1 = NSMutableAttributedString(string: "荼蘼是一款100%全真人社交平台\n")
            as1.setAttributes([.foregroundColor: UIColor.white,
                               .font: PingFangSCRegularFont(16)], range: NSMakeRange(0, as1.length))
            let as2 = NSMutableAttributedString(string: "为保证真实性，需要您视频验证")
            as2.setAttributes([.foregroundColor: UIColor.white,
                               .font: PingFangSCMediumFont(20)], range: NSMakeRange(0, as2.length))
            mas.append(as1)
            mas.append(as2)
            topLabel.attributedText = mas
            
        } else if status == .record {
            let mas = NSMutableAttributedString()
            let as1 = NSMutableAttributedString(string: "请点击下方按钮读出以下数字\n")
            as1.setAttributes([.foregroundColor: UIColor.white,
                               .font: PingFangSCRegularFont(18)], range: NSMakeRange(0, as1.length))
            let as2 = NSMutableAttributedString(string: "\(randomNumber())")
            as2.setAttributes([.foregroundColor: UIColor.theme.main,
                               .font: PingFangSCMediumFont(35)], range: NSMakeRange(0, as2.length))
            mas.append(as1)
            mas.append(as2)
            topLabel.attributedText = mas
        }
    }
    
    private func setTipsLabel() {
        if status == .demo {
            tipsLabel.text = "视频仅供内部认证使用"
        } else if status == .record {
            mainButton.setTitle("长按录制", for: .normal)
            tipsLabel.isHidden = true
        } else if status == .playback {
            mainButton.setTitle("提交", for: .normal)
            tipsLabel.isHidden = false
            tipsLabel.text = "重新拍摄"
        }
    }
    
    /// 随机数
    private func randomNumber() -> Int {
        return Int(arc4random_uniform(9000)) + 1000
    }
    
}

// MARK: ------------------ 视频相关 ----------------------
extension MTVideoVerificationViewController {
    
    /// 播放范例视频
    private func demoPlayback() {
        guard let path = Bundle.main.path(forResource: "video_verification_demo", ofType: "mp4") else { return }
        playback(withPath: path)
    }
    
    /// 播放用户拍摄视频
    private func userVideoPlayback() {
        playback(withPath: local_video_path)
    }
    
    private func playback(withPath path: String) {
        cleanPlayer()
        let playerItem = AVPlayerItem(asset: AVURLAsset(url: URL(fileURLWithPath: path)))
        let player = AVPlayer(playerItem: playerItem)
        let layer = AVPlayerLayer(player: player)
        self.playerItem = playerItem
        self.player = player
        self.playerLayer = layer
        layer.frame = self.view.bounds
        layer.videoGravity = .resizeAspectFill
        self.view.layer.insertSublayer(layer, at: 0)
        addReachEndNotification()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            player.play()
        }
    }
    /// 添加视频播放结束通知
    private func addReachEndNotification() {
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidReachEnd), name: Notification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
    }
    /// 移除视频播放结束通知
    private func removeReachEndNotification() {
        NotificationCenter.default.removeObserver(self, name: Notification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
    }
    
    /// 视频播放结束回调
    @objc
    private func playerDidReachEnd() {
        if let player = player {
            player.seek(to: .zero, toleranceBefore: .zero, toleranceAfter: .zero) { (_) in
                player.play()
            }
        }
    }
    
    private func cleanPlayer() {
        /// 移除之前的通知
        if player != nil { player = nil }
        if playerItem != nil { playerItem = nil }
        if playerLayer != nil {
            playerLayer?.removeFromSuperlayer()
            playerLayer = nil
        }
        removeReachEndNotification()
    }
    
}

// MARK: ------------------ 录制相关 ----------------------
extension MTVideoVerificationViewController {
    
    /// 开启摄像头
    private func startSession() {
        self.view.layer.insertSublayer(previewLayer, at: 0)
        self.captureSession.startRunning()
    }
    
    /// 关闭摄像头
    private func stopSession() {
        previewLayer.removeFromSuperlayer()
        self.captureSession.stopRunning()
    }
    
    /// 清理录制参数
    private func cleanRecordingConfig() {
        self.writer = nil
        self.videoInput = nil
        self.audioInput = nil
    }
    
    private var timerName: String {
        return "com.videoVerificationTimer"
    }
    
    /// 开始倒计时
    private func startCountDown() {
        MTTimer.default.scheduledTimer(withName: timerName, timeInterval: 0.1, queue: .global(), repeats: true) { [weak self] in
            guard let weakSelf = self else { return }
            weakSelf.recordTime += 0.1
            if weakSelf.recordTime > 3 && weakSelf.isRecording {
                weakSelf.videoVerificationController(didClickMainButton: weakSelf.mainButton)
            }
        }
    }
    
    /// 结束倒计时
    private func stopCountDown() {
        MTTimer.default.removeTimer(name: timerName)
    }
    
    /// 开始录制
    private func startRecording() {
        if isRecording { return }
        try? FileManager.default.removeItem(atPath: local_video_path)
        guard let writer = try? AVAssetWriter(outputURL: URL(fileURLWithPath: local_video_path), fileType: .mov) else { return }
        writer.shouldOptimizeForNetworkUse = true
        self.writer = writer
        let numOfPixel = ScreenWidth * ScreenHeight
        let bitsPerPixel: CGFloat = 12.0
        let bitsPerSecond = Int(numOfPixel * bitsPerPixel)
        let width = ScreenWidth, height = ScreenHeight

        let compressionProperties: [String : Any] = [AVVideoAverageBitRateKey : NSNumber(integerLiteral: bitsPerSecond),
                                                     AVVideoExpectedSourceFrameRateKey : NSNumber(integerLiteral: 15),
                                                     AVVideoMaxKeyFrameIntervalKey : NSNumber(integerLiteral: 15),
                                                     AVVideoProfileLevelKey : AVVideoProfileLevelH264BaselineAutoLevel]
        
        
        let outputSetting: [String:Any] = [AVVideoCodecKey : AVVideoCodecType.h264,
                                           AVVideoWidthKey : width,
                                           AVVideoHeightKey : height,
                                           AVVideoScalingModeKey : AVVideoScalingModeResizeAspectFill,
                                           AVVideoCompressionPropertiesKey : compressionProperties]
        
        let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: outputSetting)
        self.videoInput = videoInput
        videoInput.expectsMediaDataInRealTime = true
        
        let bufferAttributes: [String : Any] = [kCVPixelBufferPixelFormatTypeKey as String : NSNumber(integerLiteral: Int(kCVPixelFormatType_32BGRA))]
        self.adaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: videoInput, sourcePixelBufferAttributes: bufferAttributes)
        if writer.canAdd(videoInput) {
            writer.add(videoInput)
        }
        
        var acl: AudioChannelLayout?
        bzero(&acl, MemoryLayout<AudioChannelLayout>.size)
        acl?.mChannelLayoutTag = kAudioChannelLayoutTag_Mono
        
        let audioCompressionSettings: [String : Any] = [AVEncoderBitRatePerChannelKey : NSNumber(integerLiteral: 28000),
                                                        AVFormatIDKey : NSNumber(integerLiteral: Int(kAudioFormatMPEG4AAC)),
                                                        AVNumberOfChannelsKey : NSNumber(integerLiteral: 1),
                                                        AVSampleRateKey : NSNumber(integerLiteral: 22050)]
        
        let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioCompressionSettings)
        self.audioInput = audioInput
        audioInput.expectsMediaDataInRealTime = true
        if writer.canAdd(audioInput) {
            writer.add(audioInput)
        }
        isRecording = true
    }
    
    /// 停止录制
    private func stopRecording(completion: @escaping ()->Swift.Void) {
        if writer?.status == .completed || writer?.status == .cancelled || writer?.status == .unknown {
            return
        }
        if writer?.status == .writing {
            self.audioInput?.markAsFinished()
            self.videoInput?.markAsFinished()
        }
        self.writer?.finishWriting {
            completion()
        }
    }
    
    /*
     @method        camera(withPosition position: ) -> AVCaptureDevice?
     @abstract      用来返回是前置摄像头还是后置摄像头
     @param         position: 摄像头位置
     */
    private func camera(withPosition position: AVCaptureDevice.Position) -> AVCaptureDevice? {
        
        if #available(iOS 10.0, *) {
            let devices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: position)
            for device in devices.devices {
                if device.position == position {
                    return device
                }
            }
        } else {
            let devices = AVCaptureDevice.devices(for: .video)
            
            for device in devices {
                if device.position == position {
                    return device
                }
            }
        }
        return nil
    }
    
    /// 返回前置摄像头
    private func frontCamera() -> AVCaptureDevice {
        return camera(withPosition: .front)!
    }
    
}

// MARK: ------------------ 上传视频 ----------------------
extension MTVideoVerificationViewController {
    
    /// 上传视频
    private func upload() {
        self.player?.pause()
        let a = AlertManager.presentAlertView(message: "正在上传", autoPresent: false)
        a.isBackgroundCoverEnabled = true
        a.backgroundCoverBackgroundColor = UIColor.black.withAlphaComponent(0.5)
        a.isBackgroundCoverViewGestureEnabled = false
        a.shouldAutoDismiss = false
        a.isDismissButtonHidden = true
        self.alertView = a
        a.present()
        
        thumb = self.videoFirstFrame(URL(fileURLWithPath: local_video_path), size: CGSize(width: 160, height: 120));
        
        provider.originRequest(.uploadVideo(URL(fileURLWithPath: local_video_path)), callbackQueue: nil, progress: { (progressResponse) in
            DispatchQueue.main.async {
                a.message = String(format: "%.1f", progressResponse.progress * 100)
            }
        }) { [weak self] (result, _) in
            a.dismiss()
            guard let weakSelf = self else { return }
            weakSelf.alertView = nil
            switch result {
            case let .success(response):
                if let datas = try? response.mapJSON() as? [String: Any], let code = datas["code"] as? Int {
                    if code == 200, let videoUrl = datas["result"] as? String {
                        DispatchQueue.main.async {
                            if weakSelf.completionHandler != nil {
                                weakSelf.completionHandler!(videoUrl, weakSelf.thumb!)
                            }
                            weakSelf.navigationController?.popViewController(animated: true)
                        }
                    } else {
                        AlertManager.presentAlertView(message: "视频上传失败")
                    }
                }
                break
                
            case let .failure(error):
                AlertManager.presentAlertView(message: error.localizedDescription)
                break
            }
        }
        
    }
    
    /// 女性验证视频
//    private func validateVideo(url: String) {
//
//        user_provider.originRequest(.femaleVideoValidation(url), callbackQueue: nil, progress: nil) { [weak self] (result, _) in
//            guard let weakSelf = self else { return }
//            switch result {
//
//            case let .success(response):
//                if let datas = try? response.mapJSON() as? [String: Any], let code = datas["code"] as? Int {
//                    if code == 200 {
//                        if weakSelf.completionHandler != nil {
//                            weakSelf.completionHandler!(url, weakSelf.thumb!)
//                        }
//                        weakSelf.navigationController?.popViewController(animated: true)
//                    } else {
//                        AlertManager.presentAlertView(message: "验证失败")
//                    }
//                }
//                break
//
//            case let .failure(error):
//                AlertManager.presentAlertView(message: error.localizedDescription)
//                break
//
//            }
//        }
//    }
    
}

extension MTVideoVerificationViewController {
    // 获取视频第一帧
    func videoFirstFrame(_ videoUrl: URL, size: CGSize) -> UIImage {
        let opts = [AVURLAssetPreferPreciseDurationAndTimingKey:false]
        let urlAsset = AVURLAsset(url: videoUrl, options: opts)
        let generator = AVAssetImageGenerator(asset: urlAsset)
        generator.appliesPreferredTrackTransform = true
        generator.maximumSize = CGSize(width: size.width, height: size.height)
        //let error: Error
        do {
            let img = try generator.copyCGImage(at: CMTimeMake(value: 0, timescale: 10), actualTime: nil) as CGImage
            let image = UIImage(cgImage: img)
            return image
        } catch let error as NSError {
            debugPrint("\(error)")
            return UIImage.createImage(color: .gray, size: CGSize(width: JC_VIDEO_MSG_IMAGE_WIDTH, height: JC_VIDEO_MSG_IMAGE_HEIGHT))!
        }
    }
}

// MARK: ------------------ 所有代理 ----------------------
// MARK: ------------------ 视频输出 / 音频输出 ----------------------
extension MTVideoVerificationViewController: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate {
    
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        autoreleasepool {
            if connection == self.videoOutput.connection(with: .video) {
                objc_sync_enter(self)
                append(sampleBuffer: sampleBuffer, mediaType: .video)
                objc_sync_exit(self)
            }
            if connection == self.audioOutput.connection(with: .audio) {
                objc_sync_enter(self)
                append(sampleBuffer: sampleBuffer, mediaType: .audio)
                objc_sync_exit(self)
            }
        }
    }
    
    @discardableResult
    private func append(sampleBuffer: CMSampleBuffer, mediaType: AVMediaType) -> Bool {
        if !isRecording { return false }
        guard let writer = writer else { return false }
        
        if CMSampleBufferDataIsReady(sampleBuffer) {
            if writer.status == .unknown && mediaType == .video {
                let startTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
                writer.startWriting()
                writer.startSession(atSourceTime: startTime)
                self.startCountDown()
            } else if writer.status == .failed {
                return false
            }
            
            if writer.status == .cancelled || writer.status == .completed {
                return true
            }
            
            if mediaType == .video {
                if videoInput?.isReadyForMoreMediaData == true && writer.status == .writing {
                    let currentSampleTime = CMSampleBufferGetOutputPresentationTimeStamp(sampleBuffer)
                    if let buffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
                        adaptor?.append(buffer, withPresentationTime: currentSampleTime)
                    }
                    return true
                }
            } else {
                if audioInput?.isReadyForMoreMediaData == true && writer.status == .writing {
                    audioInput?.append(sampleBuffer)
                    return true
                }
            }
        }
        return false
    }
    
}
